package com.ahdy.service;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.regex.Pattern;

@Slf4j
@Service
public class DeepSeekService {

    private final WebClient webClient;
    private final ObjectMapper objectMapper;

    @Value("${deepseek.api.key}")
    private String apiKey;

    @Value("${deepseek.api.url:https://api.deepseek.com/v1}")
    private String apiUrl;

    @Value("${deepseek.model:deepseek-chat}")
    private String model;

    @Value("${deepseek.temperature:0.7}")
    private Double temperature;

    // 预编译正则表达式，提高性能
    private static final Pattern DATA_PREFIX_PATTERN = Pattern.compile("^data:\\s*", Pattern.MULTILINE);
    private static final Pattern MULTIPLE_SPACES_PATTERN = Pattern.compile("\\s+");
    private static final Pattern MULTIPLE_NEWLINES_PATTERN = Pattern.compile("\n{3,}");

    public DeepSeekService() {
        // 配置ObjectMapper支持UTF-8
        this.objectMapper = new ObjectMapper();

        // 配置HttpClient支持UTF-8编码
        HttpClient httpClient = HttpClient.create()
                .responseTimeout(Duration.ofSeconds(120))
                .compress(true);

        // 配置ExchangeStrategies以处理大响应和字符编码
        ExchangeStrategies strategies = ExchangeStrategies.builder()
                .codecs(configurer -> {
                    configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024); // 10MB
                    configurer.defaultCodecs().enableLoggingRequestDetails(true);
                })
                .build();

        this.webClient = WebClient.builder()
                .baseUrl("https://api.deepseek.com/v1")
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .exchangeStrategies(strategies)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
                .defaultHeader(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE + ";charset=UTF-8")
                .defaultHeader(HttpHeaders.ACCEPT_CHARSET, StandardCharsets.UTF_8.name())
                .build();
    }

    public Flux<String> callDeepSeekStream(String prompt) {
        log.info("开始调用DeepSeek API，提示词长度: {} 字符", prompt.length());

        return webClient.post()
                .uri("/chat/completions")
                .header("Authorization", "Bearer " + apiKey)
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
                .bodyValue(buildRequest(prompt))
                .retrieve()
                .onStatus(status -> !status.is2xxSuccessful(),
                        clientResponse -> clientResponse.bodyToMono(String.class)
                                .flatMap(errorBody -> {
                                    log.error("DeepSeek API错误: {} - {}", clientResponse.statusCode().value(), errorBody);
                                    return Mono.error(new RuntimeException(
                                            "AI服务暂时不可用: " + clientResponse.statusCode().value()));
                                }))
                // 关键修改：直接接收字节数据而不是字符串，避免编码丢失
                .bodyToFlux(org.springframework.core.io.buffer.DataBuffer.class)
                .map(dataBuffer -> {
                    // 直接从DataBuffer读取字节并转换为UTF-8字符串
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    org.springframework.core.io.buffer.DataBufferUtils.release(dataBuffer);

                    String chunk = new String(bytes, StandardCharsets.UTF_8);
                    log.debug("接收到原始数据块: {}", chunk.length() > 100 ? chunk.substring(0, 100) + "..." : chunk);
                    return chunk;
                })
                .filter(chunk -> !chunk.trim().isEmpty())
                .flatMap(this::parseStreamChunk)
                .map(this::cleanTextContent)
                .filter(content -> !content.trim().isEmpty())
                .doOnError(e -> log.error("流式传输错误: {}", e.getMessage()))
                .doOnComplete(() -> log.info("DeepSeek流式传输完成"));
    }

    /**
     * 解析流式数据块 - 专门处理DeepSeek API的编码问题
     */
    private Flux<String> parseStreamChunk(String chunk) {
        try {
            log.debug("正在解析数据块: {}", chunk);

            // 按行分割处理，因为SSE可能包含多行数据
            String[] lines = chunk.split("\n");

            return Flux.fromArray(lines)
                    .filter(line -> !line.trim().isEmpty())
                    .flatMap(line -> {
                        String trimmedLine = line.trim();

                        // 处理SSE格式的数据
                        if (trimmedLine.startsWith("data: ")) {
                            String jsonData = trimmedLine.substring(6).trim();

                            // 跳过结束标志
                            if (jsonData.equals("[DONE]") || jsonData.isEmpty()) {
                                return Flux.empty();
                            }

                            try {
                                // 解析JSON响应
                                DeepSeekResponse response = objectMapper.readValue(jsonData, DeepSeekResponse.class);

                                if (response.getChoices() != null && !response.getChoices().isEmpty()) {
                                    Choice choice = response.getChoices().get(0);
                                    if (choice.getDelta() != null && choice.getDelta().getContent() != null) {
                                        String content = choice.getDelta().getContent();
                                        log.debug("提取到内容: '{}'", content);
                                        return Flux.just(content);
                                    }
                                }
                                return Flux.empty();

                            } catch (JsonProcessingException e) {
                                log.warn("JSON解析失败，数据: {}", jsonData);
                                return Flux.empty();
                            }
                        }

                        // 如果不是标准SSE格式，尝试直接解析JSON
                        if (trimmedLine.startsWith("{")) {
                            try {
                                DeepSeekResponse response = objectMapper.readValue(trimmedLine, DeepSeekResponse.class);
                                if (response.getChoices() != null && !response.getChoices().isEmpty()) {
                                    Choice choice = response.getChoices().get(0);
                                    if (choice.getDelta() != null && choice.getDelta().getContent() != null) {
                                        String content = choice.getDelta().getContent();
                                        log.debug("直接提取到内容: '{}'", content);
                                        return Flux.just(content);
                                    }
                                }
                            } catch (JsonProcessingException e) {
                                log.warn("直接JSON解析失败，数据: {}", trimmedLine);
                            }
                        }

                        return Flux.empty();
                    });

        } catch (Exception e) {
            log.error("解析流式数据块失败: {}", e.getMessage());
            return Flux.empty();
        }
    }

    /**
     * 确保字符串是UTF-8编码
     */
    private String ensureUtf8(String input) {
        if (input == null) {
            return "";
        }

        try {
            // 检测字符串是否已经是正确的UTF-8编码
            byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
            String reconstructed = new String(bytes, StandardCharsets.UTF_8);

            // 如果重构后的字符串与原字符串相同，说明编码正确
            if (reconstructed.equals(input)) {
                return input;
            }

            // 尝试从ISO-8859-1转换为UTF-8（常见的乱码情况）
            byte[] isoBytes = input.getBytes(StandardCharsets.ISO_8859_1);
            String utf8String = new String(isoBytes, StandardCharsets.UTF_8);

            log.debug("字符编码转换: '{}' -> '{}'", input, utf8String);
            return utf8String;

        } catch (Exception e) {
            log.warn("字符编码转换失败，返回原始字符串: {}", e.getMessage());
            return input;
        }
    }

    /**
     * 清理文本内容 - 简化版本，专注于保持原始内容
     */
    private String cleanTextContent(String content) {
        if (content == null || content.trim().isEmpty()) {
            return "";
        }

        // 直接返回内容，减少不必要的处理
        String cleaned = content.trim();

        // 只移除明显的控制字符，保留所有正常字符
        cleaned = cleaned.replaceAll("[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]", "");

        log.debug("清理文本: '{}' (长度: {})", cleaned, cleaned.length());

        return cleaned;
    }

    /**
     * 构建请求体 - 确保UTF-8编码
     */
    private String buildRequest(String prompt) {
        try {
            // 确保prompt是UTF-8编码
            String utf8Prompt = ensureUtf8(prompt);

            DeepSeekRequest request = new DeepSeekRequest();
            request.setModel(model);
            request.setStream(true);
            request.setTemperature(temperature);
            request.setMessages(List.of(
                    new Message("system", "请提供专业、准确、有用的回答。回答要简洁明了，避免重复内容。"),
                    new Message("user", utf8Prompt)
            ));

            String requestBody = objectMapper.writeValueAsString(request);
            log.debug("构建的请求体长度: {} 字符", requestBody.length());

            return requestBody;
        } catch (JsonProcessingException e) {
            log.error("构建请求失败: {}", e.getMessage());
            throw new RuntimeException("构建AI请求失败", e);
        }
    }

    /**
     * 非流式调用（可选，用于简单场景）
     */
    public Mono<String> callDeepSeekSimple(String prompt) {
        log.info("开始非流式调用DeepSeek API");

        return callDeepSeekStream(prompt)
                .reduce("", (accumulated, chunk) -> accumulated + chunk)
                .map(this::finalTextClean)
                .doOnSuccess(result -> log.info("非流式调用完成，结果长度: {} 字符", result.length()))
                .doOnError(e -> log.error("非流式调用失败: {}", e.getMessage()));
    }

    /**
     * 最终文本清理（用于完整文本）
     */
    private String finalTextClean(String fullText) {
        if (fullText == null || fullText.trim().isEmpty()) {
            return "";
        }

        // 确保UTF-8编码
        String cleaned = ensureUtf8(fullText);

        // 1. 基础清理
        cleaned = cleanTextContent(cleaned);

        // 2. 处理段落结构
        cleaned = cleaned.replaceAll("\n\\s*\n\\s*\n", "\n\n"); // 统一段落间距

        // 3. 确保句子间合适的间距
        cleaned = cleaned.replaceAll("([。！？])([^\\s\n])", "$1 $2");

        // 4. 清理开头和结尾的特殊字符，但保留中文
        cleaned = cleaned.replaceAll("^[^\\u4e00-\\u9fa5a-zA-Z0-9]+", "");
        cleaned = cleaned.replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9。！？]+$", "");

        return cleaned.trim();
    }

    // 数据类定义
    @Data
    private static class DeepSeekRequest {
        private String model;
        private List<Message> messages;
        private Double temperature;
        private boolean stream = true;
        private Integer max_tokens = 2000;
        private Double top_p = 1.0;
        private Double frequency_penalty = 0.0;
        private Double presence_penalty = 0.0;
    }

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class DeepSeekResponse {
        private String id;
        private String object;
        private Long created;
        private String model;
        private List<Choice> choices;
        private Usage usage;
    }

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class Choice {
        private Delta delta;
        private Integer index;
        private Object logprobs;
        private String finish_reason;
    }

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class Delta {
        private String role;
        private String content;
    }

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class Usage {
        private Integer prompt_tokens;
        private Integer completion_tokens;
        private Integer total_tokens;
    }

    @Data
    private static class Message {
        private String role;
        private String content;

        public Message() {}

        public Message(String role, String content) {
            this.role = role;
            this.content = content;
        }
    }
}
